home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Mac100% 1998 November
/
MAC100-1998-11.ISO.7z
/
MAC100-1998-11.ISO
/
オンラインソフト定点観測
/
ユーティリティ
/
Mops 3.2.sea
/
Mops 3.2
/
Mops source
/
PPC source
/
pFiles
< prev
next >
Wrap
Text File
|
1998-06-12
|
16KB
|
689 lines
¥ Files - file object and loader
-39 constant EOF ¥ EOF error return
-43 constant FNF ¥ File not found ditto
-300 constant FILE-MARK
¥ Marks the start of a loaded file - we plant some useful info there.
¥ We put the file name in the dic as if it's a definition name, but use
¥ file-mark as a "handler code". Then after that we put the useful info.
¥ See extrasMod.
false value ASYNCH?
false value ENDLOAD?
false value LOG?
0 value OPEN_CNT
0 value CLOSE_ERR_CNT
forward CREATE_LOG
forward WRITE_LOG
forward OK?
string $tmp
string $marker
sysCall SFGetFile
sysCall SFPutFile
sysCall PBOpenSync
sysCall PBCloseSync
sysCall PBCreateSync
sysCall PBDeleteSync
sysCall PBReadSync
sysCall PBWriteSync
sysCall PBSetFPosSync
sysCall PBSetEOFSync
sysCall PBGetEOFSync
sysCall PBHGetFInfoSync
sysCall PBHSetFInfoSync
sysCall PBRenameSync
sysCall PBFlushVolSync
: ?DISABLE_ACTW
¥ deactivates the front window if it's one of ours. Call before
¥ putting up a dialog, since that doesn't automatically cause a
¥ deactivate event, for some strange reason.
actW IF disable: [ actW ] THEN ;
(* ***** don't want asynch stuff at this stage on the PPC, since it would
involve us in all that nasty UPP stuff...
: ASYNCH true -> asynch? ;
: IOWAIT BEGIN busy 0EXIT pause AGAIN ;
: (ASY) ¥ ( fcb -- ) Sets up for a low-level asynchronous read or write.
IOwait
-> busy setCP ;
*)
: VOLNAME? { str -- b }
reset: [ str ]
58 str chsearch: [ str ]
NIF false EXIT THEN
lim: [ str ] 2 >= ;
forward OPEN_WITH_PATHS
false value USE_PATHS?
true constant HFS? ¥ always true on PPC
variable MyDocName 28 allotx
: MyDoc ¥ ( -- addr len )
MyDocName count ;
¥ Standard file package support
: SFLOC { ¥ wd ht -- wd ht }
¥ Computes screen coordinates for top left of
¥ SF dialog box. Centers the box horizontally, and a bit above
¥ the center vertically.
screenbits -> ht -> wd 2drop
ht 3 / 80 - 0 max -> ht
wd 2/ 170 - 0 max -> wd
wd ht ;
:class SFrec super{ object }
68k_record
{ byte Good
byte count ¥ actually not used
var fType
int vRefNum
int Version
64 bytes Filename ¥ max size is 64
}
4 ordered-col fTypes ¥ list of filetypes
:m GetVRefNum: get: vRefNum ;m
:m GetName: addr: FileName ;m
:m CALL: ¥ ( routine# -- bool ) Calls a Standard File Package routine.
?disable_actw
0 ^base rot
get: good ;m
:m STDGET: ( type0 ...typeN ) { #types -- bool }
clear: fTypes #types 0>
IF #types 0 DO add: fTypes LOOP THEN
SFloc pack ¥ it's a Point, so has to be packed
0 0 #types ixAddr: fTypes 0 ^base SFGetFile
get: good ;m
:m STDPUT: { pAddr pLen nAddr nLen -- bool }
pAddr pLen pad place
SFloc
pad nAddr nLen str255
0 ^base SFPutFile
get: good ;m
;class
¥ objHandle SFHDL
¥ objPtr SFOBJ class_is SFrec
(* DO_OPEN does the hard work for OPEN: in File. First, if either the DirID
or the vol ref# is non-zero, we rashly assume we know which folder we
want, and just do an open. We also do that if we're not running under HFS.
Then, if we get through to here, we need to look at the paths. But wait!
First, we check the default folder by just doing a plain open anyway! If
this fails with a "file not found", we call ?USE_PATHS which either does
nothing (if we're not using a path designator file), or calls our PATHSMOD
module to look at a PD file and try using those paths to find the wanted
file.
*)
: DO_OPEN { perm -- rc }
1 ++> open_cnt
perm ^base 27 + c! ¥ set permission
^base 48 + @ ¥ DirID
^base 22 + w@ ¥ vol ref#
or ¥ Either non-zero?
use_paths? not or ¥ Or paths disabled?
IF ¥ Yes: just do a normal open, and get out.
^base PBOpenSync EXIT
THEN
¥ Maybe use HFS paths:
^base PBOpenSync dup 0EXIT ¥ Try default folder first
¥ -- out if we found it
dup FNF <> ?EXIT ¥ If err wasn't FNF, get out
use_paths? 0EXIT ¥ If paths disabled, out with FNF
drop ^base perm open_with_paths
;
SFRec SFObj
:class FILE super{ object } general
136 bytes FCB ¥ max parameter block (108 but for hgetvinfo)
¥ then 4-byte align for PPC
68k_record FSSpec
{ int FSvRefNum
var FSDirID
64 bytes FileName
}
:m CLEAR: ¥ Clears the fcb, except for the filename.
^base 18 erase ^base 22 + 112 erase ;m
:m SETNAMEPTR: ¥ Sets filename pointer in the FCB.
^base 142 + ^base 18 + ! ;m
:m NAME: ¥ ( addr len -- ) Assigns file name to fcb. Rest cleared.
setNamePtr: self clear: self
^base 142 + >r ¥ Addr of filename (at end of fcb)
r@ 64 blanks
( addr len ) 64 min r> >str255 drop ;m
:m SETDIRID: ¥ ( dirid -- ) Sets the DirID for the fcb
^base 48 + ! ;m
:m GETDIRID: ¥ ( -- dirid ) Gets the DirID for the fcb
^base 48 + @ ;m
:m GETFREF: ¥ ( -- fref ) Gets the file ref number.
^base 24 + w@ ;m
:m SETFREF:
^base 24 + w! ;m
:m SETVREF: ¥ ( vref# -- ) Sets the volRefNum for the fcb
^base 22 + w! ;m
:m GETVREF: ¥ ( -- vref# ) Gets the volRefNum for the fcb
^base 22 + w@ ;m
:m CLOSE: ¥ ( -- rc ) Needs to clear the file RefNum field,
¥ as advised in Mac Tech note # 102. In fact we clear
¥ the whole fcb except the name and Vref, so we can reuse
¥ the fcb for a subsequent operation without the extra info
¥ left by read and write calls being interpreted as HFS info.
^base PBCloseSync getVref: self clear: self setVref: self
dup if 1 ++> close_err_cnt else -1 ++> open_cnt then ;m
:m OPEN: ¥ ( -- rc )
0 do_open ;m
:m OPENREADONLY:
1 do_open ;m
:m NEW: ^base PBCreateSync ;m
:m DELETE: ^base PBDeleteSync ;m
:m MOVETO: ¥ ( byteoffset -- rc ) Positions relative to start of file
^base $ 2E + !
^base PBSetFPosSync ;m
:m POS: ¥ ( -- byteoffset )
inline{ ^base $ 2E + @} ;m
:m SETEOF: ¥ ( pos -- rc ) Sets end-of-file to absolute byte position
^base 28 + ! ^base PBSetEOFSync ;m
:m CREATE: { ¥ volID -- rc }
¥ Opens and resets file or creates new if not present.
1 ++> open_cnt
^base PBOpenSync ¥ Attempt to open - don't use paths
?dup
IF dup FNF =
IF drop
new: self ?dup NIF ^base PBOpenSync THEN
THEN
ELSE
0 setEOF: self
THEN ;m
:m CREATENEW: ¥ ( -- rc ) Like create:, but if file exists it's deleted
¥ and created totally new.
delete: self drop
create: self ;m
:m LAST: ¥ Positions to end of file.
big# moveto: self drop ;m
:m SIZE: ¥ ( -- #bytes ) Returns logical eof for file currently open
^base PBGetEOFSync drop ^base 28 + @ ;m
:m BYTESREAD: ¥ ( -- n ) Returns actual bytes read.
^base 40 + @ ;m
:m FCB: ( -- fcb ) ^base ;m
:m RESULT: ¥ ( -- rc ) Returns the last I/O result code.
^base 16 + w@ ;m
:m MODE: ¥ ( posMode -- ) Sets position mode
inline{ ^base 44 + w!} ;m
:m WAIT: ¥ ( -- rc ) Waits for asynch I/O on this file to finish.
BEGIN ^base busy =
NIF ^base 16 + w@x EXIT THEN
pause
AGAIN ;m
:m ?WAIT: ¥ ( rc1 -- rc2 )
asynch?
NIF drop wait: self
ELSE false -> asynch?
THEN ;m
:m READ: { addr len -- rc }
0 mode: self
addr ^base $ 20 + !
len ^base $ 24 + !
^base PBReadSync ;m
:m READLINE: { addr maxLen -- rc } ¥ Reads terminating with CR
$ 0D80 mode: self
addr ^base $ 20 + !
maxLen ^base $ 24 + !
^base PBReadSync ;m
:m WRITE: { addr len -- rc }
0 mode: self
addr ^base $ 20 + !
len ^base $ 24 + !
^base PBWriteSync ;m
:m SETNAME: ¥ Gets name from input stream, and assigns to fcb.
¥ The name can have embedded blanks and be delimited
¥ by " ... ", or just terminate at the end of line.
bl skip-src+ & " parse-word name: self ;m
:m GETNAME: ¥ ( -- addr len ) Returns filename
addr: fileName count ;m
:m PRINT: ¥ Prints the filename.
getName: self type ;m
:m GETFILEINFO: ¥ ( -- rc ) Fills the parameter block with file info
^base PBHGetFInfoSync ;m
:m SETFILEINFO: ¥ ( -- rc )
^base PBHSetFInfoSync ;m
:m SET: { ftyp sig -- } ¥ Sets file type, signature.
getDirID: self ¥ Save DirID
0 setDirID: self ¥ and clear it (otherwise we'll get
getFileInfo: self drop ¥ "file not found")
sig ^base $ 24 + ! ¥ Set signature
ftyp ^base $ 20 + ! ¥ Set type
0 setDirID: self
setFileInfo: self drop
setDirID: self ;m ¥ Restore DirID
¥ :m DRIVE: ¥ ( drive# -- ) set default drive to drive#
¥ clear: self setVRef: self ^base PBSetVolSync
¥ IF 165 die THEN ;m
:m ACCEPT: { addr len ¥ #chrs eof? -- #chrs eof? } ¥ ACCEPTs from disk.
echo? IF addr len erase THEN ¥ So the typed line is OK
addr len readLine: self -> eof?
bytesRead: self eof? NIF 1- THEN -> #chrs
#chrs 0= eof? and IF 0 true EXIT THEN
addr #chrs + c@ 13 <>
IF ¥ Overlength line. Probably a comment.
BEGIN ¥ Gobble to CR or EOF
pad 100 readLine: self -> eof?
eof?
IF true
ELSE pad bytesRead: self 1- + c@ 13 =
THEN
UNTIL
THEN
#chrs -> len
echo?
IF addr len type cr THEN
BEGIN ¥ Loop to convert tabs to blanks
addr len 9 scan -> len -> addr
len
WHILE
bl addr c!
REPEAT
#chrs false ;m
:m RENAME: { taddr tlen -- rc }
taddr tlen str255
^base 28 + ! ^base PBRenameSync ;m
:m GETTYPE: ¥ ( -- type )
^base 32 + @ ;m
:m FLUSHVOL:
^base PBFlushVolSync drop ;m
:m CLASSINIT:
clear: self setNamePtr: self ;m
¥ Standard file package calls. If the value SFDlgHook is non-zero, we take it as the
¥ address of a dialog hook routine.
private
:m SFPCALL: ¥ ( various get? -- b ) Calls a Standard File Package routine
classinit: self ¥ Make sure name pointer is right
IF stdGet: SFobj ELSE stdPut: SFobj THEN
IF getVRefNum: SFobj clear: self setVref: self
getName: SFobj count addr: fileName place
true
ELSE
false
THEN
;m
public
:m STDGET: ¥ ( type0 ...typeN #types -- bool )
true sfpCall: self ;m
:m STDPUT: ¥ ( pAddr pLen nAddr nLen -- bool )
false sfpCall: self ;m
;class
file FFCB
(*
$ BC1F ' ffcb 2- w!
' file ' ffcb 4+ reloc!x ¥ Make fFcb a FILE objPtr
' file ffcb 8 - reloc!x
-4 fFcb 4 - w!
2 ffcb 2 - w!
*)
¥ GetDirID returns the dirID of the last directory opened by a
¥ standard file call.
syscall LMGetCurDirStore
: GETDIRID LMGetCurDirStore ;
¥ FileList keeps a stack of open load files for nested loads.
objPtr TOPFILE class_is file
:class FILELIST super{ handleArray }
:m DROP:
top: super ¥ Give error if empty
close: topFile drop
drop: super
size: super NIF nilP ELSE obj: self THEN
-> topFile
false -> endload? ;m
:m PUSHNEW: ¥ Adds a new file to the stack
['] file pushNewObj: self
false -> endload?
obj: self -> topFile ¥ Note this locks the file object
¥ -- this is what we want.
0 setVref: topFile ;m
:m CLEAR: ¥ Removes all currently open files
false -> endload?
get: size 0EXIT
." File stack: " cr top: self
get: size
FOR print: topFile cr drop: self
NEXT ;m
;class
10 fileList LOADFILE
0 value FILESTART_DP
0 value CNT
0 value SvLATEST
(*
: LOGIT
state 0EXIT ¥ Out if we're not compiling
here filestart_DP - pad w!
pos: topFile src-len -
pad 2+ !
pad 6 add: $lg1 ;
0 value LASTPOS
: LOGCR
state 0EXIT
here lastPos <= ?EXIT
here -> lastPos
pad 14 erase
here filestart_DP - pad w!
latest svLatest <> IF true pad 4+ c! latest -> svLatest THEN
pad 14 add: $lg2 ;
*)
:f FREFILL ¥ ( -- flag ) Does a refill from a file.
echo?
IF ?pause
ELSE cnt NIF ?pause 20 -> cnt else 1 --> cnt THEN
THEN
¥ log? IF logCR THEN
tib tibLen accept: topfile ( #chrs eof? ) -> endload? #tib !
set_source endload? 0=
;f
: (fRefill) fRefill ; ¥ for backwards compatibility
: (LD)
BEGIN
endload? IF false -> endload? EXIT THEN
topfile -> source-ID Frefill IF interpret THEN
state not echo? and fWind? and IF ." >" THEN
AGAIN ;
false value DO_CR?
false value marker_there?
: ?file_open_error { OSErr -- }
OSErr 0EXIT ¥ out if no error
getName: topfile type
OSErr FNF = IF 132 die THEN ¥ file not found
OSErr cr . 155 die ¥ other error opening file
;
: BL>01 ¥ ( addr len -- ) Replaces blanks with 01's in the string.
bounds
?DO i c@ bl = IF $ 01 i c! THEN
LOOP
;
: 01>BL ¥ ( addr len -- ) Replaces 01's with blanks in the string.
bounds
?DO i c@ $ 01 = IF bl i c! THEN
LOOP
;
: FNAME>MNAME ¥ ( addr len -- ) Takes the passed-in filename, and converts it to
¥ the corresponding file marker name in $marker.
new: $marker put: $marker
& : <chsearch: $marker negate skip: $marker
<step: $marker delete: $marker
all: $marker bl>01 ¥ replace any blanks
begin: $marker " m__" insert: $marker ¥ prepend "m__"
reset: $marker
;
: MNAME>FNAME ¥ ( addr len -- ) Takes the passed-in marker name, and
¥ converts it to the corresponding filename in $marker.
3 /string ¥ skip the "m__"
new: $marker put: $marker all: $marker 01>bl ¥ and recover any blanks
reset: $marker
;
0 value mk_cfa
: mark_file ( addr len -- )
" marker" sFind nip NIF 2drop EXIT THEN ¥ out if MARKER not defined yet
fname>mname
begin: $marker " marker " insert: $marker
lock: $marker all: $marker evaluate
release: $marker
true -> marker_there?
CDP 10 - -> mk_cfa ¥ markers have 2 spare bytes at the cfa,
1 mk_cfa w! ¥ so we store 1 there to show this is a file
¥ mark
;
: LOADTOP { ¥ svCurs svDP svCDP svDepth len rc -- }
¥ Interprets the file as a Mops source file.
openReadOnly: topfile ?file_open_error
marker_there? false -> marker_there?
IF
getFileInfo: topfile -> rc
topFile 48 + @ code, ¥ put source dirID after marker info
¥ at offs 10 from cfa
topFile 76 + @ code, ¥ then the mod date at offs 14
getName: topfile ¥ this will be the full pathname
dup -> len
CDP place len 1+ ++> CDP ¥ store it after the mod date,
¥ at offs 18
code_align
¥ now for some mysterious reason, if we've just saved the file
¥ in Quick Edit and we get the file info, we get EOF the first time
¥ we try to read from it. So we'll do a dummy read, then close
¥ and re-open it.
pad 1 read: topfile drop close: topfile drop
openReadOnly: topfile ?file_open_error
THEN
curs? -> svCurs -curs
cr
size: loadFile 2* spaces ." Loading: "
getName: topfile type
DP -> svDP CDP -> svCDP depth -> svDepth
false -> endload? false -> do_cr?
(ld)
close: topfile drop
do_cr?
IF cr size: loadFile 2* ELSE 2 THEN spaces true -> do_cr?
." Code: "
CDP
svCDP IF svCDP ELSE code_start THEN - .
DP svDP - ." data: " .
size: loadFile 1 <= IF cr THEN
depth svDepth <> IF cr ." Warning - stack depth changed" cr THEN
svCurs -> curs?
;
: ENDLOAD true -> endload? 0 -> src-len ; ppc_only
¥ Nesting loader. Usage: // filename
: (load)
room2 ¥ ( -- code-room data-room )
512 < IF 204 die THEN ¥ bail out on insufficient free space
1024 < IF 203 die THEN
getName: topfile mark_file
loadTop
drop: loadFile
;
: //
pushNew: loadFile setName: topFile
(load)
; ppc_only
: INCLUDED { addr len -- } ¥ loads the named file, if not loaded already
addr len fname>mname
all: $marker sfind nip
IF release: $marker EXIT THEN ¥ Found - nothing else to do
pushNew: loadFile
addr len name: topFile
(load)
;
: NEED ( --<filename> )
word" count ¥ Get name from input
included ;
¥ CL2 is the next cleanup word - it cleans up all file stuff on abort,
¥ as well as whatever we were doing before (see CL1 in file Class).
: NOMOD
-1 -> modcode -1 -> moddata
¥ -1 -> modcode_start -1 -> modcode_limit
¥ -1 -> moddata_start -1 -> moddata_limit
-1 -> modcode_comp_start
-1 -> moddata_comp_start
0 -> compmod 0 -> comp_seg#
;
: clFiles
clear: loadfile close: ffcb drop
nilP -> topfile
nomod
¥ release: $lg1 release: $lg2
¥ ['] null -> logvec
false -> endload?
false -> savingDic?
;
: filinit
¥ fFcb 18 + @ ¥ Name pointer - doc name may not be in fFcb
¥ count 32 min myDocName place
classinit: loadfile nilP -> topfile
false -> MRopen?
;
¥ ' filinit -> objinit - filinit now called from init1 in cg7
¥ ' clFiles -> abortvec